package com.yjd.merchant.app.api.order;

import com.alibaba.fastjson.JSON;
import com.yjd.comm.base.control.MerchantBaseControl;
import com.yjd.comm.base.enums.DbWREnums;
import com.yjd.comm.base.model.PagerModel;
import com.yjd.comm.enums.OrderRefuseEnum;
import com.yjd.comm.enums.RefundOrderStatus;
import com.yjd.comm.enums.StagesStatusEnum;
import com.yjd.comm.fundservice.service.IFundChannelService;
import com.yjd.comm.merchant.dto.*;
import com.yjd.comm.order.dto.ReturnFeeDto;
import com.yjd.comm.order.model.OrderModel;
import com.yjd.comm.order.service.IOrderProjectService;
import com.yjd.comm.order.service.IOrderService;
import com.yjd.comm.repayment.model.RepaymentDataModel;
import com.yjd.comm.repayment.service.IRepaymentDataService;
import com.yjd.comm.user.dto.ContactInfo;
import com.yjd.comm.user.model.UserDataModel;
import com.yjd.comm.user.dto.WorkInfo;
import com.yjd.comm.user.service.IUserDataService;
import com.yjd.comm.user.util.UserUtil;
import com.yjd.comm.util.*;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 商户APP 订单相关操作
 * Created by yangchangyan on 2017/11/28.
 */
@Controller("com.yjd.merchant.app.api.OrderControl")
@Scope("prototype")
@RequestMapping("/merchant/order")
public class OrderControl extends MerchantBaseControl {

    @Resource
    private IOrderService orderService;

    @Resource
    private IOrderProjectService orderProjectService;

    @Resource
    private IUserDataService userDataService;

    @Resource
    private IRepaymentDataService repaymentDataService;

    @Resource
    private IFundChannelService fundChannelService;

    /**
     * 订单处理
     * type 1 通过, 2 拒绝
     *
     * @param
     * @return
     * @throws
     */
    @RequestMapping(value = "/process")
    public void orderProcess(Long order_id, int type) throws Exception {
        if(null == order_id || (type != 1 && type != 2)){
            this.errorMsg("信息不正确");
            return;
        }

        OrderModel orderModel = orderService.getModelById(order_id, DbWREnums.READ);
        if (orderModel == null) {
            this.errorMsg("订单不存在");
            return;
        }

        if(type == 1){
            /**
             * 如果orderModel.getFund_channel() > 0，说明使用的第三方资金，分两个异步过程：
             * 1、先调用第三方贷款申请
             * 2、等待异步回调，根据是否通过做相应处理：
             *  通过：生成还款报表、更新商户资金
             *  未通过：拒绝订单
             */
            if(orderModel.getFund_channel().intValue() > 0){
                this.fundChannelService.loanApply(super.getMerchantId(), orderModel.getOrder_id());
                this.successMsg("贷款申请处理中");
                return;
            }

            /**
             * 否则，没有走资金渠道，保持原有业务不变
             */
            orderService.merchantConfirm(super.getMerchantId(), orderModel.getOrder_id());
            this.successMsg("订单确认成功");
        } else {
            orderService.merchantRefuse(super.getMerchantId(), orderModel.getOrder_id(), OrderRefuseEnum.C, OrderRefuseEnum.C.getLabel());
            this.successMsg("订单拒绝成功");
        }

    }

    /**
     * 订单处理列表
     * @param type 1：待确认 2：已确认 3：已取消
     *
     * @return
     * @throws
     */
    @RequestMapping(value = "/process/list")
    public void processList(Integer type, Integer page, Integer rows) throws Exception{
        Map<String, Object> filter = new HashMap<String, Object>();
        if(null == rows){
            rows = 10;
        }
        filter.put("rows", rows);
        if(null == page){
            page = 1;
        }
        filter.put("page", page);
        filter.put("org_id", super.getMerchantSession().getOrg_id());
        filter.put("sort", " create_time desc ");
        List statusList = new ArrayList();
        if(1 == type){
            // 根据下单时间进行排序
            statusList.add(StagesStatusEnum.MERCHANT_HANDING.getCode());
        } else if(2 == type){
            // 根据确认时间进行排序
            statusList.add(StagesStatusEnum.REPAYMENTING.getCode());
            statusList.add(StagesStatusEnum.REPAYMENED.getCode());
        } else if(3 == type){
            // 根据订单取消时间进行排序 仅显示商户拒绝的取消订单
            statusList.add(StagesStatusEnum.MERCHANT_REFUSAL.getCode());
        }
        filter.put("statusList", statusList);

        OrderHandleInfoDto infoDto = null;
        List<OrderHandleInfoDto> infoDtos = new ArrayList<OrderHandleInfoDto>();
        PagerModel pagerModel = orderService.getPageModel(filter, DbWREnums.READ);
        List<OrderModel> orderDatas = pagerModel.getDataList();
        if(null != orderDatas && orderDatas.size() > 0){
            List<Long> userIds = new ArrayList<Long>();
            for(OrderModel order : orderDatas){
                userIds.add(order.getUser_id());
            }

            Map<Long, UserDataModel> userDatas = userDataService.getModelMapByIds(userIds, DbWREnums.READ);
            for(OrderModel om: orderDatas){
                infoDto = new OrderHandleInfoDto();
                infoDto.setOrder_id(om.getOrder_id());
                if(1 == type){
                    // 显示下单时间
                    infoDto.setTime(DateUtil.timestampToDateString(om.getCreate_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
                } else if(2 == type){
                    // 显示确认时间
                    infoDto.setTime(DateUtil.timestampToDateString(om.getConfirm_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
                } else if(3 == type){
                    // 显示订单取消时间
                    infoDto.setTime(DateUtil.timestampToDateString(om.getConfirm_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
                }
                if(userDatas.containsKey(om.getUser_id())){
                    infoDto.setId_name(userDatas.get(om.getUser_id()).getId_name());
                }
                infoDto.setOrder_amount(om.getOrder_amount());
                infoDto.setLoan_amount(om.getLoan_amount());
                infoDto.setPayment(om.getPayment());
                infoDto.setStatus(om.getStatus());
                infoDto.setType(type);
                infoDtos.add(infoDto);
            }
        }

        this.successData(FrameUtil.newHashMap("orderList", infoDtos, "type", type));
    }

    /**
     * 订单处理列表——订单详情
     * @param type 1：待确认 2：已确认 3：已取消
     *
     * @return
     * @throws
     */
    @RequestMapping(value = "/process/detail")
    public void processDetail(Long order_id, Integer type) throws Exception{
        if(null == order_id || null == type){
            this.errorMsg("信息不正确");
            return;
        }

        OrderModel order = orderService.getModelById(order_id, DbWREnums.READ);
        if(null == order){
            this.errorMsg("订单不存在");
            return;
        }

        UserDataModel userData = userDataService.getModelById(order.getUser_id(), DbWREnums.READ);
        if(null == userData){
            userData = new UserDataModel();
        }

        // 订单信息
        OrderHandleInfoDto infoDto = new OrderHandleInfoDto();

        // 还款计划
        List<RepaymentPlanDto> planDtos = new ArrayList<RepaymentPlanDto>();

        infoDto.setOrder_id(order.getOrder_id());
        infoDto.setId_name(userData.getId_name());
        infoDto.setOrder_amount(order.getOrder_amount());
        infoDto.setLoan_amount(order.getLoan_amount());
        infoDto.setPayment(order.getPayment());
        if(1 == type){
            // 显示下单时间
            infoDto.setTime(DateUtil.timestampToDateString(order.getCreate_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
        } else if(2 == type){
            // 显示确认时间
            infoDto.setTime(DateUtil.timestampToDateString(order.getConfirm_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
            // 查询所有还款报表
            List<RepaymentDataModel> allRepaymentDataModel = repaymentDataService.getModelList(
                    FrameUtil.newHashMap("order_id", order.getOrder_id()), DbWREnums.READ);
            RepaymentPlanDto plan = null;
            for(RepaymentDataModel rdm : allRepaymentDataModel){
                plan = new RepaymentPlanDto();
                plan.setPeriod(rdm.getPeriod());
                plan.setEstimation_repayment_time(DateUtil.timestampToDateString(rdm.getEstimation_repayment_time(), DateUtil.PATTERN_yyyy_MM_dd));
                plan.setRepayment_status(rdm.getRepayment_status());
                planDtos.add(plan);
            }
        } else if(3 == type){
            // 显示订单取消时间
            infoDto.setTime(DateUtil.timestampToDateString(order.getConfirm_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
        }

        Map result = FrameUtil.newHashMap("orderInfo", infoDto, "repaymentPlan", planDtos);
        result.putAll(getCommonInfo(type, order, userData));
        this.successData(result);
    }

    /**
     * 退单处理
     * type 1 通过, 2 拒绝
     *
     * @param
     * @return
     * @throws
     */
    @RequestMapping(value = "/chargeback/process")
    public void refundProcess(Long order_id, int type) throws Exception {
        if (StringUtil.isEmpty(order_id)) {
            this.errorMsg("无效的订单号");
            return;
        }

        if (type != RefundOrderStatus.REFUND_PASS.getCode() &&
                type != RefundOrderStatus.REFUND_REFUSE.getCode()) {
            this.errorMsg("无效操作");
            return;
        }

        OrderModel order = orderService.getModelById(order_id, DbWREnums.READ);
        if (null == order) {
            this.errorMsg("订单不存在");
            return;
        }

        // 登陆的商户与订单所属商户对应不上
        Long org_id = super.getMerchantId();
        if (order.getOrg_id().longValue() != org_id) {
            this.errorMsg("不能操作此订单");
            return;
        }

        orderService.refundProcess(org_id, order.getOrder_id(), RefundOrderStatus.parse(type), OrderRefuseEnum.C, OrderRefuseEnum.C.getLabel());

        this.successMsg("处理成功");
    }

    /**
     * 退单处理列表
     * @param type 1：待确认 2：已确认 3：已拒绝
     *
     * @return
     * @throws
     */
    @RequestMapping(value = "/chargeback/list")
    public void chargebackList(Integer type, Integer page, Integer rows) throws Exception{
        Map<String, Object> filter = new HashMap<String, Object>();
        if(null == rows){
            rows = 10;
        }
        filter.put("rows", rows);
        if(null == page){
            page = 1;
        }
        filter.put("page", page);
        filter.put("org_id", super.getMerchantSession().getOrg_id());
        filter.put("sort", " create_time desc ");

        List statusList = new ArrayList();
        if(1 == type){
            statusList.add(StagesStatusEnum.MERCHANT_CONFIRM_CANCEL.getCode());
        } else if(2 == type){
            statusList.add(StagesStatusEnum.MERCHANT_CANCEL.getCode());
        } else if(3 == type){
            filter.put("refund_status", "2");
            statusList.add(StagesStatusEnum.REPAYMENTING.getCode());
            statusList.add(StagesStatusEnum.REPAYMENED.getCode());
        }
        filter.put("statusList", statusList);

        OrderHandleInfoDto infoDto = null;
        List<OrderHandleInfoDto> infoDtos = new ArrayList<OrderHandleInfoDto>();
        PagerModel pagerModel = orderService.getPageModel(filter, DbWREnums.READ);
        List<OrderModel> orderDatas = pagerModel.getDataList();
        if(null != orderDatas && orderDatas.size() > 0){
            List<Long> userIds = new ArrayList<Long>();
            for(OrderModel order : orderDatas){
                userIds.add(order.getUser_id());
            }

            Map<Long, UserDataModel> userDatas = userDataService.getModelMapByIds(userIds, DbWREnums.READ);

            for(OrderModel om: orderDatas){
                infoDto = new OrderHandleInfoDto();
                infoDto.setOrder_id(om.getOrder_id());
                if(1 == type){
                    // 显示下单时间
                    infoDto.setTime(DateUtil.timestampToDateString(om.getCreate_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
                } else if(2 == type){
                    // 显示确认时间
                    infoDto.setTime(DateUtil.timestampToDateString(om.getApprove_refund_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
                } else if(3 == type){
                    // 显示订单取消时间
                    infoDto.setTime(DateUtil.timestampToDateString(om.getApprove_refund_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
                }
                if(userDatas.containsKey(om.getUser_id())){
                    infoDto.setId_name(userDatas.get(om.getUser_id()).getId_name());
                }
                infoDto.setOrder_amount(om.getOrder_amount());
                infoDto.setLoan_amount(om.getLoan_amount());
                infoDto.setPayment(om.getPayment());
                infoDto.setOrder_no(om.getOrder_no());
                infoDto.setStatus(om.getStatus());
                infoDto.setType(type);
                infoDtos.add(infoDto);
            }
        }

        this.successData(FrameUtil.newHashMap("orderList", infoDtos, "type", type));
    }

    /**
     * 退单处理列表——退单详情
     * @param type 1：待确认 2：已确认 3：已拒绝
     *
     * @return
     * @throws
     */
    @RequestMapping(value = "/chargeback/detail")
    public void chargebackDetail(Long order_id, Integer type) throws Exception{
        if(null == order_id || null == type){
            this.errorMsg("信息不正确");
            return;
        }

        OrderModel order = orderService.getModelById(order_id, DbWREnums.READ);
        if(null == order){
            this.errorMsg("订单不存在");
            return;
        }

        UserDataModel userData = userDataService.getModelById(order.getUser_id(), DbWREnums.READ);
        if(null == userData){
            userData = new UserDataModel();
        }



        // 订单信息
        OrderHandleInfoDto infoDto = new OrderHandleInfoDto();

        infoDto.setOrder_id(order.getOrder_id());
        infoDto.setId_name(userData.getId_name());
        infoDto.setOrder_amount(order.getOrder_amount());
        infoDto.setLoan_amount(order.getLoan_amount());
        infoDto.setPayment(order.getPayment());
        infoDto.setOrder_no(order.getOrder_no());
        if(1 == type){
            // 显示下单时间
            infoDto.setTime(DateUtil.timestampToDateString(order.getCreate_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
        } else if(2 == type){
            // 显示确认时间
            infoDto.setTime(DateUtil.timestampToDateString(order.getApprove_refund_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
            order.setConfirm_time(order.getApprove_refund_time()); // 显示退单审批时间
        } else if(3 == type){
            // 显示订单取消时间
            infoDto.setTime(DateUtil.timestampToDateString(order.getApprove_refund_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
            order.setConfirm_time(order.getApprove_refund_time()); // 显示退单审批时间
        }

        Map result = FrameUtil.newHashMap("orderInfo", infoDto);
        result.putAll(getCommonInfo(type, order, userData));
        this.successData(result);
    }

    /**
     * 返回都要显示的订单信息：订单详细信息，用户信用信息，订单包含的项目列表
     */
    private Map getCommonInfo(Integer type, OrderModel order, UserDataModel userData) throws Exception {

        // 订单详细信息
        OrderHandleDetailDto detailDto = new OrderHandleDetailDto();
        detailDto.setOrder_no(order.getOrder_no());
        detailDto.setId_name(userData.getId_name());
        detailDto.setOrder_amount(order.getOrder_amount());
        detailDto.setType(type);
        detailDto.setCreate_time(DateUtil.timestampToDateString(order.getCreate_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
        detailDto.setTime("");
        if(null != order.getConfirm_time() && order.getConfirm_time() > 0){
            detailDto.setTime(DateUtil.timestampToDateString(order.getConfirm_time(), DateUtil.PATTERN_yyyy_MM_dd_HH_mm_ss));
        }
        detailDto.setLoan_amount(order.getLoan_amount());
        detailDto.setPeriod(order.getPeriod());
        detailDto.setPayment(order.getPayment());

        // 用户信用信息
        OrderHandleCreditInfoDto creditInfoDto = new OrderHandleCreditInfoDto();
        OrderStatisticDto statisticDto = orderService.orderStatisticByUser(order.getUser_id());
        creditInfoDto.setUser_id(order.getUser_id());
        creditInfoDto.setOrderCount(statisticDto.getOrderCount());
        creditInfoDto.setRepaymentOrderCount(statisticDto.getRepaymentOrderCount());
        creditInfoDto.setRepaymentedOrderCount(statisticDto.getRepaymentedOrderCount());
        creditInfoDto.setOverDueOrderCount(statisticDto.getOverDueOrderCount());
        creditInfoDto.setCredit_line(userData.getCredit_line());
        creditInfoDto.setMobileNumberCompleted(1);

        ContactInfo contactInfo = null;
        WorkInfo workInfo = null;
        try{
            if(StringUtil.isNotEmpty(userData.getJob_info())){
                workInfo = JSON.parseObject(userData.getJob_info(), WorkInfo.class);
            }
            if(StringUtil.isNotEmpty(userData.getContacts())){
                contactInfo = JSON.parseObject(userData.getContacts(), ContactInfo.class);
            }
        }catch (Exception e){}

        creditInfoDto.setContactInfoCompleted(0);
        if(UserUtil.isContactInfoCompleted(contactInfo)){
            creditInfoDto.setContactInfoCompleted(1);
        }

        creditInfoDto.setJobInfoCompleted(0);
        if(UserUtil.isJobInfoCompleted(workInfo)){
            creditInfoDto.setJobInfoCompleted(1);
        }

        creditInfoDto.setIdNameCompleted(0);
        if(StringUtil.isNotEmpty(userData.getId_name())){
            creditInfoDto.setIdNameCompleted(1);
        }

        // 订单包含的项目列表
        List<EverPurchaseProjectDto> projectDtos = orderProjectService.everPurchaseProject(
                FrameUtil.newHashMap("order_id", order.getOrder_id()));

        return FrameUtil.newHashMap(
                "orderDetail", detailDto,
                "projects", projectDtos,
                "creditInfo", creditInfoDto);
    }

    /**
     * 预期收益
     *
     * @return
     * @throws
     */
    @RequestMapping(value = "/prospective/profit")
    public void prospectiveProfit(ProfitDto profits) throws Exception{

        List<ProspectiveProfitDto> profitList = new ArrayList<>();
        if(null != profits || null != profits.getProfits() || profits.getProfits().size() > 0){
            for(ProspectiveProfitDto profit : profits.getProfits()){
                ReturnFeeDto returnFeeDto =  FeeCalcUtil.countA(profit.getCapital(), profit.getApr(), profit.getPeriod(),FrameUtil.getTime());
                profit.setInterest(returnFeeDto.getInterest());
                profit.setRepayment(NumberUtil.formatNumber4(ArithUtil.add(profit.getCapital(), returnFeeDto.getInterest())));
                profitList.add(profit);
            }
        }


        this.successData(FrameUtil.newHashMap("profitList", profitList));
    }
}
